#include "autoupdatedialog.h"
#include "base/service/downloader.h"
#include "base/service/service.h"
#include "base/utils/packs.h"
#include "base/utils/utils.h"
#include "msgutils.h"
#include <QApplication>
#include <QDesktopServices>
#include <QDir>
#include <QKeyEvent>
#include <QLabel>
#include <QProcess>
#include <QProgressBar>
#include <QPushButton>
#include <QtDebug>
#include <QVBoxLayout>

#ifdef Q_OS_WIN
#include <Windows.h>
#endif

namespace yc {

AutoUpdateDialog::AutoUpdateDialog(QWidget* parent)
    : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint), task_(nullptr)
{
    setAttribute(Qt::WA_DeleteOnClose, true);
    setWindowTitle(tr("Update"));

    QVBoxLayout* main_layout = new QVBoxLayout(this);
    main_layout->setSizeConstraint(QLayout::SetMaximumSize);
    main_layout->setContentsMargins(20, 20, 20, 20);
    main_layout->setSpacing(10);
    main_layout->addStretch(1);

    QLabel* status_label = new QLabel(tr("Downloading..."), this);
    status_label->setObjectName("status");
    main_layout->addWidget(status_label);

    progress_bar_ = new QProgressBar(this);
    progress_bar_->setObjectName("progress");
    progress_bar_->setRange(0, 100);
    progress_bar_->setTextVisible(false);
    main_layout->addWidget(progress_bar_);
    main_layout->addStretch(1);

    QPushButton* cancel_button = new QPushButton(tr("Cancel"), this);
    cancel_button->setObjectName("normal");
    main_layout->addWidget(cancel_button, 0, Qt::AlignRight);

    cancel_button->setAutoDefault(false);
    cancel_button->setDefault(false);
    connect(cancel_button, &QPushButton::clicked, this, [this] {
        if (task_) {
            disconnect(task_, nullptr, this, nullptr);
            task_->terminate();
        }
        close();
    });

    adjustSize();
}

AutoUpdateDialog::~AutoUpdateDialog()
{
    if (task_) {
        disconnect(task_, nullptr, this, nullptr);
        delete task_;
    }
}

int AutoUpdateDialog::start(Service* service, const QList<Pack>& packs)
{
    if (!task_ && !packs.empty()) {
        const QString url = packs.first().url;
        QString file_name = baseutils::filenameFromUrl(url);
        task_ = new Downloader(service, QString(), QDir::temp(), false, 0, this);
        task_->addResource(DownloadResource { url, file_name, 0 });
        connect(task_, &Downloader::downloaded, this, [this](const QString& file_name) {
            disconnect(task_, nullptr, this, nullptr);
#ifdef Q_OS_WIN
            const QString params = QString("/D=%1").arg(
                    QDir::toNativeSeparators(QApplication::applicationDirPath()));
            HINSTANCE ret = ::ShellExecuteA(nullptr, "open", file_name.toUtf8().constData(),
                                            params.toUtf8().constData(), nullptr, SW_SHOWNORMAL);
            if (reinterpret_cast<intptr_t>(ret) <= 32) {
                auto r = msgutils::msgBox(this, tr("Prompt"),
                                          tr("Failure to decompress the update package. Try again "
                                             "later or download the latest installation package "
                                             "from the official website and install it manually."),
                                          QMessageBox::Ok | QMessageBox::Close);
                if (r == QMessageBox::Ok) {
                    QDesktopServices::openUrl(QUrl("https://www.yingce.top"));
                }
            } else {
                Q_EMIT beginToInstall();
            }
#else
            if (QProcess::execute("open", QStringList(file_name)) < 0) {
                auto r = msgutils::msgBox(
                        this, tr("Prompt"),
                        tr("Failure to decompress the update package. Try again "
                           "later or download the latest installation package "
                           "from the official website and install it manually."),
                        QMessageBox::Ok | QMessageBox::Close);
                if (r == QMessageBox::Ok) {
                    QDesktopServices::openUrl(QUrl("https://www.yingce.top"));
                }
            } else {
                Q_EMIT beginToInstall();
            }
#endif
            close();
        });
        connect(task_, &Downloader::failed, this, [this](int error, const QString& message) {
            Q_UNUSED(error)
            disconnect(task_, nullptr, this, nullptr);
            msgutils::msgBox(this, tr("Prompt"), tr("Failed to download file, ") + message);
            close();
        });
        connect(task_, &Downloader::progress, this,
                [this](qint64 bytes_received, qint64 bytes_total) {
                    int percent = 10;
                    if (bytes_total > 0) {
                        percent = 100 * qreal(bytes_received) / qreal(bytes_total);
                    }
                    progress_bar_->setValue(percent);
                });
        task_->start();
    }
    return exec();
}

void AutoUpdateDialog::keyPressEvent(QKeyEvent* ke)
{
    if (ke->matches(QKeySequence::Close)) {
        return ke->ignore();
    }
    return QDialog::keyPressEvent(ke);
}

} // namespace yc
